package fr.jade.resources.joram.wrapper;

import java.util.Properties;

import javax.jms.TopicConnectionFactory;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.api.control.LifeCycleController;
import org.objectweb.fractal.util.Fractal;
import org.objectweb.joram.client.jms.ConnectionFactory;
import org.objectweb.joram.client.jms.admin.AdminException;
import org.objectweb.joram.client.jms.admin.AdminModule;
import org.objectweb.joram.client.jms.tcp.TcpConnectionFactory;
import org.objectweb.joram.client.jms.tcp.TopicTcpConnectionFactory;

import fr.jade.base.JadeBaseComponent;
import fr.jade.fraclite.api.control.NoSuchAttributeException;
import fr.jade.resources.joram.api.ConnectionFactoryInterface;
import fr.jade.resources.joram.api.JndiInterface;
import fr.jade.util.FractalNavigator;
import fr.jade.util.FractalUtil;
import fr.jade.util.JadeException;


public class ConnectionFactoryWrapper extends JadeBaseComponent implements ConnectionFactoryInterface, LifeCycleController {

	private boolean started;

	private Properties serverConfig;

	private javax.jms.ConnectionFactory myConnFact;
	
	private String name;

	private String listAtt[] = {"name"};

	/**
	 * Access to Jndi Context
	 */
	private Context context;

	private void initializeContext() {
		JndiInterface jndiItf = null;
		try {
			jndiItf = (JndiInterface)Fractal.getBindingController(JoramUtils.getServerComponent(self)).lookupFc("jndi");
		} catch (NoSuchInterfaceException e1) {
			e1.printStackTrace();
		} catch (AdminException e1) {
			e1.printStackTrace();
		}
		System.out.println("JNDI: Host " + jndiItf.getHost() + " Port " + jndiItf.getPort());
		Properties jndiprops = new Properties();
		jndiprops.setProperty("java.naming.factory.initial","fr.dyade.aaa.jndi2.client.NamingContextFactory");
		jndiprops.setProperty("java.naming.factory.host", jndiItf.getHost());
		jndiprops.setProperty("java.naming.factory.port", jndiItf.getPort());

		Thread ct = Thread.currentThread();
		ClassLoader cl = ct.getContextClassLoader();
		ct.setContextClassLoader(getClass().getClassLoader());
		try {
			context = new InitialContext(jndiprops);
		} catch (NamingException e) {
			e.printStackTrace();
		}
		ct.setContextClassLoader(cl);
	}

	private void initServerConfig() throws NoSuchInterfaceException, AdminException, NoSuchAttributeException, JadeException{
		serverConfig = new Properties();
		Component server = JoramUtils.getServerComponent(self);
		serverConfig.put("hostName", FractalUtil.getAttributeController(FractalNavigator.getNode(server)).getAttribute("hostName"));
		serverConfig.put("port", JoramUtils.PORT_NUMBER_START + Integer.parseInt(FractalUtil.getAttributeController(server).getAttribute("sid")));
		serverConfig.put("sid",FractalUtil.getAttributeController(server).getAttribute("sid"));
		serverConfig.put("userAdmin", FractalUtil.getAttributeController(server).getAttribute("userAdmin"));
		serverConfig.put("passAdmin", FractalUtil.getAttributeController(server).getAttribute("passAdmin"));
	}

	private void registerInJNDI(){
		initializeContext();
		try {
			context.bind(name, myConnFact);
		} catch (NamingException e) {
			e.printStackTrace();
		}
		System.out.println("Connection Factory " + name	+ " registered in Jndi");
	}

	public String getFcState() {
		return started ? STARTED : STOPPED;
	}

	public void startFc() throws IllegalLifeCycleException {
	  if(!started && JoramUtils.serverIsStarted(self)){
  		try {
  			initServerConfig();
  
  			// Creates a connection factory
  			TopicConnectionFactory con = TopicTcpConnectionFactory.create(serverConfig.getProperty("hostName"), JoramUtils.PORT_NUMBER_START + Integer.parseInt(serverConfig.getProperty("sid")));
  			AdminModule.connect(con, serverConfig.getProperty("userAdmin"), serverConfig.getProperty("passAdmin"));
  			
  			myConnFact = (ConnectionFactory) TcpConnectionFactory.create(serverConfig.getProperty("hostName"), JoramUtils.PORT_NUMBER_START + Integer.parseInt(serverConfig.getProperty("sid")));
  			
  			log("Connection Factory " + name	+ " created");
  			AdminModule.disconnect();
  
  			// Registers the connection Factory in JNDI
  			registerInJNDI();
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  		started = true;
	  }
	}

	public void stopFc() throws IllegalLifeCycleException {
	  if(started){
  	  started = false;
  		try {
        context.unbind(name);
      } catch (NamingException e) {
        log(e);
        throw new IllegalLifeCycleException("Can't stop topic");
      }
	  }
	}

	public String getAttribute(String attName) throws NoSuchAttributeException {
		if(attName.equals("name"))
			return this.name;
		else
			return super.getAttribute(attName);
	}

	public String[] listFcAtt() {
		return super.concat(listAtt, super.listFcAtt());
	}

	public void setAttribute(String attName, String value) throws NoSuchAttributeException {
		if(attName.equals("name"))
			this.name = value;
		else
			super.setAttribute(attName, value);
	}


	public javax.jms.ConnectionFactory getConnectionFactory() {
		return myConnFact;
	}

}
